package org.smallreunion.service;

import java.util.Map;

import org.slim3.datastore.Datastore;
import org.slim3.memcache.Memcache;
import org.smallreunion.meta.CounterShardMeta;
import org.smallreunion.model.CounterShard;
import org.smallreunion.model.constract.CounterShardType;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;

/**
 * シャーディングカウンタサービス
 *
 * @author Sinmetal
 *
 */
public class CounterShardService {

    CounterShardMeta meta = new CounterShardMeta();

    public int getCount(CounterShardType name) {
        if (Memcache.contains(name)) {
            return Memcache.get(name);
        }
        int total = 0;
        Map<Key, CounterShard> counterShards =
            Datastore.getAsMap(meta, CounterShard.getKeyList(name));
        for (CounterShard counterShard : counterShards.values()) {
            total += counterShard.getCount();
        }
        return total;
    }

    public Key increment(CounterShardType name) {
        Key key = CounterShard.createKey(name);

        Transaction tx = Datastore.beginTransaction();
        try {
            CounterShard counter = Datastore.getOrNull(meta, key);
            if (counter == null) {
                counter = CounterShard.getInstance(name);
                counter.setKey(key);
            }
            counter.increment();
            Key result = Datastore.put(counter);
            tx.commit();
            incrementMemcache(name);
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
        }
    }

    protected void incrementMemcache(CounterShardType name) {
        if (!Memcache.contains(name)) {
            return;
        }
        Memcache.increment(name, 1);
    }
}
